#ifdef _WIN32
#include "input_win32.h"
#include "algebra.h"
#include <cctype>

using namespace krryn;
using namespace krryn::system_imp;
using namespace krryn::system;

bool input_manager_win32::wnd_proc_accept(HWND hWnd, UINT uMsg){
	switch(uMsg){
		case WM_KEYUP:
		case WM_KEYDOWN:
		case WM_MOUSEMOVE:
		case WM_LBUTTONUP:
		case WM_MBUTTONUP:
		case WM_RBUTTONUP:
		case WM_LBUTTONDOWN:
		case WM_MBUTTONDOWN:
		case WM_RBUTTONDOWN:
		case WM_MOUSEWHEEL:
			return hWnd == m_hWnd;
	}

	return false;
}

LRESULT CALLBACK input_manager_win32::wnd_proc_input(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
	switch(uMsg){
		case WM_KEYDOWN:
		case WM_KEYUP:
			{
				if((wParam >= 'A' && wParam <= 'Z') || (wParam >= '0' && wParam <= '9')){
					if(uMsg == WM_KEYUP){
						post_keyup_message((system::keycode_t)std::tolower((int)wParam));
					}else{
						post_keydown_message((system::keycode_t)std::tolower((int)wParam));
					}
				}
			}
			break;
		case WM_MOUSEMOVE:
			{
				math::point l_Point(LOWORD(lParam), HIWORD(lParam));
				post_mouse_move(l_Point);
			}
			break;
		case WM_LBUTTONUP:
			post_mouse_up(btn_left);
			break;
		case WM_MBUTTONUP:
			post_mouse_up(btn_middle);
			break;
		case WM_RBUTTONUP:
			post_mouse_up(btn_right);
			break;
		case WM_LBUTTONDOWN:
			post_mouse_down(btn_left);
			break;
		case WM_MBUTTONDOWN:
			post_mouse_down(btn_middle);
			break;
		case WM_RBUTTONDOWN:
			post_mouse_down(btn_right);
			break;
		case WM_MOUSEWHEEL:
			post_mouse_scroll(
				GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? scroll_up : scroll_down, 
				(int)math::abs(GET_WHEEL_DELTA_WPARAM(wParam)) / WHEEL_DELTA);
			break;
	}

	return 0;
}

void input_manager_win32::post_keyup_message(system::keycode_t a_Key){
	for(keyboard_list_t::iterator i = m_KeyboardListeners.begin(); i != m_KeyboardListeners.end(); i++){
		(*i)->key_up(a_Key);
	}
}

void input_manager_win32::post_keydown_message(system::keycode_t a_Key){
	for(keyboard_list_t::iterator i = m_KeyboardListeners.begin(); i != m_KeyboardListeners.end(); i++){
		(*i)->key_down(a_Key);
	}
}

void input_manager_win32::post_mouse_move(math::point a_Point){
	math::point l_Relative = a_Point - m_PreviousPosition;
	for(mouse_list_t::iterator i = m_MouseListeners.begin(); i != m_MouseListeners.end(); i++){
		(*i)->mouse_move_abs(a_Point);
		(*i)->mouse_move_rel(l_Relative);
	}
	m_PreviousPosition = a_Point;
}

void input_manager_win32::post_mouse_up(mouse_button a_Button){
	for(mouse_list_t::iterator i = m_MouseListeners.begin(); i != m_MouseListeners.end(); i++){
		(*i)->button_up(a_Button);
	}
}

void input_manager_win32::post_mouse_down(mouse_button a_Button){
	for(mouse_list_t::iterator i = m_MouseListeners.begin(); i != m_MouseListeners.end(); i++){
		(*i)->button_down(a_Button);
	}
}

void input_manager_win32::post_mouse_scroll(mouse_scroll a_Scroll, int a_Amount){
	for(mouse_list_t::iterator i = m_MouseListeners.begin(); i != m_MouseListeners.end(); i++){
		for(int t = 0; t < a_Amount; t++){
			(*i)->scroll_wheel(a_Scroll);
		}
	}
}

#endif